Conversation
allow wallet and coins object to sign using the BitGo key if the passphrase is not provided during signing Ticket: WCN-217-2
When no walletPassphrase is present in the request body or environment, pass undefined to tradingAccount.signPayload() instead of throwing. The SDK routes passphrase-less signing through KMS internally. Ticket: WCN-215-1
| export interface SignPayloadParameters { | ||
| payload: string | Record<string, unknown>; | ||
| walletPassphrase: string; | ||
| walletPassphrase?: string; |
There was a problem hiding this comment.
Nit: add jsdoc describing why this is optional.
| if (!params.walletPassphrase) { | ||
| return this.signPayloadByBitGoKey(params); | ||
| } |
There was a problem hiding this comment.
First check the wallet setting.
If there is no walletPassphrase and wallet.userKeySigningRequired is set to true, then throw an error.
There was a problem hiding this comment.
The backend will check it anyways, but best to do the validation here as well.
| } | ||
|
|
||
| /** | ||
| * Signs the payload of a trading account via the trading account BitGo key stored in a remote KMS |
There was a problem hiding this comment.
- Signs the payload of a trading account via the BitGo key
| private async signPayloadByBitGoKey(params: Omit<SignPayloadParameters, 'walletPassphrase'>): Promise<string> { | ||
| const walletData = this.wallet.toJSON(); | ||
| if (walletData.userKeySigningRequired) { | ||
| throw new Error('Wallet must use user key to sign ofc transaction, please provide the wallet passphrase'); |
There was a problem hiding this comment.
throw new Error('Wallet must use user key to sign ofc transaction, please provide the wallet passphrase or visit your wallet settings page to configure one.');
| if (walletData.keys.length < 2) { | ||
| throw new Error('Wallet does not support BitGo signing'); | ||
| } |
There was a problem hiding this comment.
throw new Error('Wallet does not support BitGo signing. Please reach out to support@bitgo.com to resolve this issue.');
| async signMessage(key: { prv: string }, message: string): Promise<Buffer>; | ||
| async signMessage(keyOrWallet: { prv: string } | Wallet, message: string): Promise<Buffer> { | ||
| if (!(keyOrWallet instanceof Wallet)) { | ||
| return super.signMessage(keyOrWallet as { prv: string }, message); |
There was a problem hiding this comment.
do you still need the cast here? I thought the type would be narrowed by the time you are inside this if block.
| if (!(keyOrWallet instanceof Wallet)) { | ||
| return super.signMessage(keyOrWallet as { prv: string }, message); | ||
| } | ||
| const signatureHexString = await (keyOrWallet as Wallet).toTradingAccount().signPayload({ payload: message }); |
There was a problem hiding this comment.
same here, I'm surprised you still need a cast after type narrowing.
|
|
||
| /** | ||
| * Returns the wallet passphrase from the environment, or undefined if not set. | ||
| * Unlike getWalletPwFromEnv, this does not throw when the env variable is absent. |
There was a problem hiding this comment.
Why not just update getWalletPwFromEnv to make the throwing behaviour configurable?
zahin-mohammad
left a comment
There was a problem hiding this comment.
lgtm, just a few suggestions/comments.
Commit 1: allowing trading wallet transaction signing on Trading Account Objects
make wallet passphrase optional when signing OFC transactions.
if not present, the SDK attempts to sign using the wallet's BitGo key instead.
Commit 2: allowing trading wallet transaction signing on Wallet and Coins object
The following are all of the currently valid methods to create a signature on an OFC wallet's
payloadstringofcToken.signMessage({prv}, message): encrypts the message locally using prvofcToken.signTransaction(params): signs a half signed transaction by calling the above methodwallet.baseCoin.signMessage: see abovewallet.baseCoin.signTransaction: see abovewallet.signTransaction(params): signs a half signed transaction by getting the prv through a wallet passphrase then callingthis.baseCoin.signTransactionwallet.prebuildAndSignTransaction(params): builds and sign a transaction by callingwallet.signTransactionwallet.prebuildAndSignTransaction(e.g. sendMany)wallet.toTradingAccount().signPayload: signs a half signed transaction using the wallet passphraseChanges in commit 1 address path 8 already.
For paths that creates the signature using methods of wallet object (i.e. 5-7), all of them eventually calls
wallet.signTransaction, which pass itselfthisas an argument towallet.baseCoin.signTransaction(see here), allowing us to sign via BitGo key if we add the implementation toofcTokenAs for
ofcToken.signMessage, add overloads to the method to allow SDK user to pass in the wallet object instead, which creates the signature via the BitGo key.Note that the
walletPassphraseis already an optional parameter when calling wallet level methods.